//------------------------------------------------------------------------------
// <copyright company="Telligent Systems">
//     Copyright (c) Telligent Systems Corporation.  All rights reserved.
// </copyright> 
//------------------------------------------------------------------------------

using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using CommunityServer.Components;
using CommunityServer.Controls;
using CommunityServer.Discussions.Components;

namespace CommunityServer.Discussions.Controls 
{
    // *********************************************************************
    //  ThreadView
    //
    /// <summary>
    /// This server control is used to display top level threads. Note, a thread
    /// is a post with more information. The Thread class inherits from the Post
    /// class.
    /// </summary>
    /// 
    // ********************************************************************/
    public class ThreadView : TemplatedWebControl
    {
        #region Child Controls

        //Control threadDisplay;
        Control noThreadsToDisplay;
        internal Repeater announcements;
        internal Repeater threads;
		internal ForumRepeater subForums;
		Control subForumContainer;
        ForumPager pager, pager2;
        CurrentPage currentPage, currentPage2;
        ThreadSet threadSet;
        DateFilter dateFilter;
        InlineTextEdit forumName;
        InlineTextEdit forumDescription;
        Label forumFilterText;
        EmailNotificationDropDownList ddlTracking;
        ThreadSortDropDownList threadSortddl;
        SortOrderDropDownList sortOrderddl;
        ForumDropDownList forumFilterddl;
        Button sortButton;
        Button rememberSettingsButton;
        HideReadPostsDropDownList hideReadPosts;
        FilterUsersDropDownList filterUsers;

        LinkButton moveThreads;
        ForumImageButton newPostButton;
		ForumImageButton poll;
		ForumImageButton newPostButtonDown;
		ForumImageButton forumSettings;
        HtmlTableRow filterTopicRow;
        HtmlTableRow emailNotificationRow;
        //Control postbackSourceControl;

		AggregateRssLink aggregateRssLink;
		RssLink rssLink;

        CSContext csContext = CSContext.Current;
        internal Forum forum;
        bool hideReadPost = false;
        bool authUseLocalFilter = false; // Use local filter when user is authenticated, otherwise use previous remembered values.
        string anonymousQuerystringFilter = "PageIndex={0}&sb={1}&d={2}&df={3}";
        string authQuerystringFilter = "PageIndex={0}&sb={1}&d={2}&df={3}&uf={4}&hrp={5}&lf={6}";

        ThreadViewMode mode = ThreadViewMode.Default;
        SortThreadsBy sortBy = SortThreadsBy.LastPost;
        SortOrder sortOrder = SortOrder.Descending;
        ThreadDateFilterMode dateFilterMode = ThreadDateFilterMode.TwoMonths;
        ThreadUsersFilter userFilter = ThreadUsersFilter.All;
		PostMediaType postMedia = PostMediaType.Empty;


        #endregion

        public ThreadView()
        {
            try 
            {
                int modeFromQS = Int32.Parse( csContext.Context.Request.QueryString["mode"] );

                // What mode are we running in?
                //
                if (modeFromQS > 0)
                    mode = (ThreadViewMode) modeFromQS;
            } 
            catch 
            {
                mode = ThreadViewMode.Default;
            }

			dateFilterMode = csContext.SiteSettings.DefaultThreadDateFilter;
        }

        protected override void OnInit(EventArgs e) 
        {
            if (SkinName == null)                
                ExternalSkinFileName = "View-Threads.ascx";
            else 
                ExternalSkinFileName = SkinName;
			
            // Private messages should not be seen like this
            //
            //if ((csContext.ForumID == 0) && (csContext.User.IsAnonymous))
            if (csContext.SectionID == 0)
                throw new CSException(CSExceptionType.SectionNotFound, csContext.SectionID.ToString());

            base.OnInit(e);
        }
		
        protected override void OnLoad(EventArgs e) 
        {
            DataBind();

            base.OnLoad(e);
        }

        #region DataBind

        public override void DataBind() 
        {
            base.DataBind();
            
            // Because the table of threads is databound, visibility on the the checkbox column 
            // for the multiple move thread functionality is done as part of the databinding process,
            // in the skin.  Because the move multiple threads link button is not databound, and to 
            // keep the skin as clean as possible its visibility is set here.  
            if (!csContext.User.IsForumAdministrator &&
                !csContext.User.IsModerator)
            {
                if (moveThreads != null)
                {
                    moveThreads.Visible = false;
                }
            }

            #region Init by ThreadViewMode
            // Init by ThreadViewMode
            //
            switch (mode) 
            {
                case ThreadViewMode.Active:
                    if (forumName != null)
                        forumName.Text = ResourceManager.GetString("ViewActiveThreads_Title");

                    Head.AddSiteNameTitle(ResourceManager.GetString("ViewActiveThreads_Title"),Context);
                    UsersOnline.SetLocation(ResourceManager.GetString("ViewActiveThreads_Title"));

                    if (forumDescription != null)
                        forumDescription.Text = ResourceManager.GetString("ViewActiveThreads_Description");                        
                    break;

                case ThreadViewMode.Unanswered:
                    if (forumName != null)
                        forumName.Text = ResourceManager.GetString("ViewUnansweredThreads_Title");

                    Head.AddSiteNameTitle(ResourceManager.GetString("ViewUnansweredThreads_Title"),Context);
                    UsersOnline.SetLocation(ResourceManager.GetString("ViewUnansweredThreads_Title"));

                    if (forumDescription != null)
                        forumDescription.Text = ResourceManager.GetString("ViewUnansweredThreads_Description");
                    break;

                case ThreadViewMode.NotRead:
                    if (forumName != null)
                        forumName.Text = ResourceManager.GetString("ViewNotReadThreads_Title");

                    Head.AddSiteNameTitle(ResourceManager.GetString("ViewNotReadThreads_Title"),Context);
                    UsersOnline.SetLocation(ResourceManager.GetString("ViewNotReadThreads_Title"));

                    if (forumDescription != null)
                        forumDescription.Text = ResourceManager.GetString("ViewNotReadThreads_Description");
                    break;

                case ThreadViewMode.PrivateMessages:
                    if (forumName != null)
                        forumName.Text = ResourceManager.GetString("PrivateMessages_Title");

                    Head.AddSiteNameTitle(ResourceManager.GetString("PrivateMessages_Title"),Context);
                    UsersOnline.SetLocation(ResourceManager.GetString("PrivateMessages_Title"));

                    if (forumDescription != null)
                        forumDescription.Text = ResourceManager.GetString("PrivateMessages_Description");
                    break;

				case ThreadViewMode.Videos:
					if (forumName != null)
						forumName.Text = ResourceManager.GetString("ViewVideos_Title");

                    Head.AddSiteNameTitle(ResourceManager.GetString("ViewVideos_Title"),Context);
                    UsersOnline.SetLocation(ResourceManager.GetString("ViewVideos_Title"));

					if (forumDescription != null)
						forumDescription.Text = ResourceManager.GetString("ViewVideos_Description");
					break;

                case ThreadViewMode.MyForums:
                    // Don't need filter when viewing My Forums
                    if (forumFilterddl != null)
                        forumFilterddl.Visible = false;

                    if (forumFilterText != null)
                        forumFilterText.Visible = false;

                    if(forumName != null)
                        forumName.Text = ResourceManager.GetString("ViewMyForumsThreads_Title");

                    Head.AddSiteNameTitle(ResourceManager.GetString("ViewMyForumsThreads_Title"),Context);
                    UsersOnline.SetLocation(ResourceManager.GetString("ViewMyForumsThreads_Title"));

                    if(forumDescription != null)
                        forumDescription.Text = ResourceManager.GetString("ViewMyForumsThreads_Description");
                    break;

                default:
                    //don't need filter when viewing a forum by default
                    if (forumFilterddl != null)
                        forumFilterddl.Visible = false;

                    if (forumFilterText != null)
                        forumFilterText.Visible = false;
                    break;
            }
            #endregion

            if (sortButton != null) 
                sortButton.Text = ResourceManager.GetString("ViewThreads_SortThreads");

            if (rememberSettingsButton != null) 
                rememberSettingsButton.Text = ResourceManager.GetString("ViewThreads_RememberSettings");

            if (dateFilter == null)
                dateFilter = new DateFilter();

            // Apply filtering values on controls when not postback
            //
            if (!Page.IsPostBack)
                SetFilteringControlValues();

            // Populate threads list
            //
            DateTime dateFilterValue;
            int forumID = csContext.SectionID;
            
            #region Load forum details by ThreadViewMode
            // Load forum details by ThreadViewMode
            //
            try 
            {
                switch (mode) 
                {
                    case ThreadViewMode.Active:                        
                        if (forumFilterddl.SelectedForum > 0)
                            forum = Forums.GetForum( forumFilterddl.SelectedForum, true, true );
                        else
                            forum = new Forum(forumFilterddl.SelectedForum);
                        break;

                    case ThreadViewMode.Unanswered:
                        if (forumFilterddl.SelectedForum > 0)
                            forum = Forums.GetForum( forumFilterddl.SelectedForum, true, true );
                        else
                            forum = new Forum(forumFilterddl.SelectedForum);
                        break;

                    case ThreadViewMode.NotRead:
                        if (forumFilterddl.SelectedForum > 0)
                            forum = Forums.GetForum( forumFilterddl.SelectedForum, true, true );
                        else
                            forum = new Forum(forumFilterddl.SelectedForum);
                        break;

                    case ThreadViewMode.PrivateMessages:
                        //TODO: 0 can not be used to hard code Private Forum
                        forum = Forums.GetForum(0);
                        break;

                    case ThreadViewMode.MyForums:
                        // Don't need filter when viewing My Forums
                        break;

					case ThreadViewMode.Videos:
						if (forumFilterddl.SelectedForum > 0)
							forum = Forums.GetForum(forumFilterddl.SelectedForum, true, true);
						else
							forum = new Forum(forumFilterddl.SelectedForum);
						break;

                    default:
                        // Don't need filter when viewing a forum by default
                        if (forumID > 0) 
                        {
                            forum = Forums.GetForum( forumID, true, true );
                            Permissions.AccessCheck( forum, Permission.View, csContext.User );

							bool isAdmin = csContext.User.IsForumAdministrator;
							if(isAdmin)
								AjaxManager.Register(this,"QuickForumEdit");

							if(forumName != null)
							{
								forumName.Text = forum.Name;
								if(isAdmin)
								{
									forumName.AjaxClientID = this.ClientID;
									forumName.AjaxFunction= string.Format("QuickForumEdit.UpdateForumName('{0}',this.innerHTML,null);",this.ClientID);
								}
		
							}
                            if(forumDescription != null) {
                                forumDescription.Text = forum.Description;
								if(isAdmin)
								{
									forumDescription.AjaxClientID = this.ClientID;
									forumDescription.AjaxFunction= string.Format("QuickForumEdit.UpdateForumDescription('{0}',this.innerHTML,null);",this.ClientID);
								}

                            }

                            Head.AddMetaDescription(Globals.HtmlEncode(forum.Description),Context);
                            Head.AddSiteNameTitle(Globals.HtmlEncode(forum.Name),Context);
                            if(this.forum.IsPrivate)
                            {
                                UsersOnline.PrivateLocation();
                            }
                            else
                            {
                                UsersOnline.SetLocation(forum.Name);
                            }

                        }
                        break;
                }
            } 
            catch( Exception ex )
            {
                throw new CSException(CSExceptionType.SectionNotFound, csContext.SectionID.ToString(), ex );
            }
            #endregion


            #region Check user's permissions
            // Check user's permissions on forum.
            // Also set new post button.
            //
            if (mode != ThreadViewMode.MyForums)
            {
                User user = csContext.User;
                if( forum.SectionID > 0 ) 
                {
                    // TODO: Rollback to initial approach after permissions on 
                    // subforums are implemented.
                    //
                    // Note: This is a temporary solution untill permissions on subforums 
                    // are handled properly.
                    ForumPermission p;

                    if (forum.ParentID > 0)
                    {
                        // Lookup for parent forum and verify credentials against it
                        //
                        Section parentSection = Forums.GetTopmostParentSection( forum.ParentID );
                        if (parentSection == null)
                            throw new CSException( CSExceptionType.AccessDenied );

                        p = parentSection.ResolvePermission( user ) as ForumPermission;
                    } 
                    else
                    {
                        // No subforums
                        //
                        p = forum.ResolvePermission( user ) as ForumPermission;
                    }
                                            
                    /* Initial approach
                    ForumPermission p = forum.ResolvePermission( user ) as ForumPermission;
                    */

                    if( !p.Read )
                        throw new CSException( CSExceptionType.AccessDenied );

					if ((!p.Post) || ((mode != ThreadViewMode.Default) && (mode != ThreadViewMode.PrivateMessages)))
					{
						if (newPostButton != null)
							newPostButton.Visible = false;

						if (newPostButtonDown != null)
							newPostButtonDown.Visible = false;
					}

					if ((!p.CreatePoll) || ((mode != ThreadViewMode.Default) && (mode != ThreadViewMode.PrivateMessages)))
					{
						if (poll != null)
							poll.Visible = false;
					}

					if ((mode != ThreadViewMode.Default) && (mode != ThreadViewMode.PrivateMessages))
					{
						if (forumSettings != null)
							forumSettings.Visible = false;
					}
                }
            }
            else
            {
				if (newPostButton != null) 
					newPostButton.Visible = false;

				if (poll != null)
					poll.Visible = false;

				if (newPostButtonDown != null)
					newPostButtonDown.Visible = false;

				if (forumSettings != null)
					forumSettings.Visible = false;
            }
            #endregion

            #region Get a populated ThreadSet
            // Get a populated thread set
            //
            if ((forum != null) && (forum.SectionID > 0))
                forumID = forum.SectionID;
            else
                if (mode != ThreadViewMode.PrivateMessages)
                    forumID = forumFilterddl.SelectedForum;

            // Fix #1308: don't show private messages unless if asked
            // occurs when forumGroup or blank is selected
            if ((forumID == 0) && (mode != ThreadViewMode.PrivateMessages))
            {
                forumID = -1;						// show all
                forumFilterddl.SelectedIndex = 0;	// select all filter
            }

            if (dateFilterMode == ThreadDateFilterMode.LastVisit)
                dateFilterValue = csContext.User.GetUserCookie().LastVisit;
            else
                dateFilterValue = dateFilter.SelectedDate;

            ForumThreadQuery query = new ForumThreadQuery();
            query.ForumID = forumID;
            query.PageIndex = pager.PageIndex;
            query.PageSize = pager.PageSize;
            query.ThreadsNewerThan = dateFilterValue;
            query.SortBy = this.sortBy;
            query.Order = this.sortOrder;
            query.UserFilter = this.userFilter;
			query.PostMedia = this.postMedia;

            switch (mode) 
            {
                case ThreadViewMode.Active:
                    query.ActiveTopics = true;
                    query.UnReadOnly = this.hideReadPost;
                    threadSet = Threads.GetThreads(query);

                    pager.UrlPattern = this.BuildQuerystringFilter(ForumUrls.Instance().PostsActivePaged( forumID ), mode);
                    break;

                case ThreadViewMode.Unanswered:    
                    
                    query.UnReadOnly = this.hideReadPost;
                    query.UnAnsweredOnly = true;
                    threadSet = Threads.GetThreads(query);

                    pager.UrlPattern = this.BuildQuerystringFilter(ForumUrls.Instance().PostsUnansweredPaged( forumID ), mode);
                    break;

                case ThreadViewMode.NotRead:

                    query.UnReadOnly = true;
                    threadSet = Threads.GetThreads(query);

                    pager.UrlPattern = this.BuildQuerystringFilter(ForumUrls.Instance().PostsNotReadPaged( forumID ), mode);
                    break;
                
                case ThreadViewMode.MyForums:

                    query.UserFilter = ThreadUsersFilter.HideTopicsParticipatedIn;
                    query.UnReadOnly = this.hideReadPost;
                    threadSet = Threads.GetThreads(query);

                    pager.UrlPattern = this.BuildQuerystringFilter(SiteUrls.Instance().UserMyForums, mode);

                    break;
                
                case ThreadViewMode.PrivateMessages:
                    query.ForumID = 0;
                    query.UserFilter = ThreadUsersFilter.All;
                    threadSet = Threads.GetThreads(query);
                    pager.UrlPattern = this.BuildQuerystringFilter( SiteUrls.Instance().UserPrivateMessages, mode );
                    break;

				case ThreadViewMode.Videos:
					query.PostMedia = PostMediaType.Video;
					threadSet = Threads.GetThreads(query);
					break;

                default:
                    if (forumID > 0) 
                    {
                        query.UnReadOnly = this.hideReadPost;
                        threadSet = Threads.GetThreads(query);
                    }   
                    else
                        throw new CSException(CSExceptionType.SectionNotFound);

                    pager.UrlPattern = this.BuildQuerystringFilter( ForumUrls.Instance().Forum( forumID ), mode );

                    break;
            }

			// If we have sub forums display them
			if ((null != forum) && (forum.Sections.Count > 0)) 
			{
				subForumContainer.Visible = true;

				// Sort subforums by name
				forum.Sections.Sort(new SectionSorter(SectionSortBy.Name));

				subForums.DataSource = forum.Sections;
				subForums.DataBind();
			}

            if ((threadSet.Announcements.Count > 0) && 
                (mode != ThreadViewMode.Unanswered) && 
                (mode != ThreadViewMode.Active) ) 
            {
                announcements.DataSource = threadSet.Announcements;
                announcements.DataBind();
            } 
            else if ((mode != ThreadViewMode.Unanswered) && 
                (mode != ThreadViewMode.Active))  
            {
                announcements.DataSource = null;
                announcements.DataBind();
            }

            // Do we have posts to display?
            //
            if (threadSet.Threads.Count > 0) 
            {
                threads.DataSource = threadSet.Threads;
                threads.DataBind();
            } 
            else 
            {
                threads.DataSource = null;
                threads.DataBind();
            }

            // Do we have announcements or threads?
            //
            if ((threads.DataSource == null) && 
                (announcements.DataSource == null)) 
            {
                noThreadsToDisplay.Visible = true;
				
				if (moveThreads != null)
				{
					moveThreads.Visible = false;
				}
				
            } 
            else 
            {
                noThreadsToDisplay.Visible = false;
            }
            #endregion

            pager.TotalRecords = currentPage.TotalRecords = threadSet.TotalRecords;
            if (pager2 != null)
            {
                pager2.PageIndex = pager.PageIndex;
                pager2.UrlPattern = pager.UrlPattern;
                pager2.TotalRecords = pager.TotalRecords;
            }

            currentPage.TotalPages = pager.CalculateTotalPages();
            currentPage.PageIndex = pager.PageIndex;
            if (currentPage2 != null)
            {
                currentPage2.TotalRecords = currentPage.TotalRecords;
                currentPage2.TotalPages = currentPage.TotalPages;
                currentPage2.PageIndex = pager.PageIndex;
            }

			if ((aggregateRssLink != null) && (forumFilterddl.SelectedIndex == 0))
			{
				switch (mode)
				{
					case ThreadViewMode.Active:
					case ThreadViewMode.Unanswered:
					case ThreadViewMode.Videos:
						aggregateRssLink.Mode = mode;
						aggregateRssLink.Visible = true;
						break;
				}

				if (rssLink != null)
					rssLink.Visible = false;
			}

			if ((rssLink != null) && (forumFilterddl.SelectedIndex != 0))
			{
				csContext.SectionID = forumFilterddl.SelectedForum;

				rssLink.Mode = mode;
				rssLink.Visible = true;

				if (aggregateRssLink != null)
					aggregateRssLink.Visible = false;
			}
        }
		
        #endregion		

		[AjaxMethod(IncludeControlValuesWithCallBack=false)]
		public void UpdateForumName(string name)
		{
			if(csContext.User.IsForumAdministrator)
			{
				Forum f = Forums.GetForum(csContext.SectionID);
				if(f != null)
				{
					f.Name = name;
					Sections.UpdateSection(f);
				}
			}
		}

        [AjaxMethod(IncludeControlValuesWithCallBack=false)]
        public void UpdateForumDescription(string description) 
		{
			if(csContext.User.IsForumAdministrator)
			{
				Forum f = Forums.GetForum(csContext.SectionID);
				if(f != null) 
				{
					f.Description = description;
					Sections.UpdateSection(f);
				}
			}
        }


        #region Skin
                
        protected override void AttachChildControls() 
        {
            forumName = (InlineTextEdit) FindControl("ForumName");
            forumDescription = (InlineTextEdit) FindControl("ForumDescription");
            //threadDisplay = FindControl("ThreadDisplay");
            noThreadsToDisplay = FindControl("NoThreadsToDisplay");
            filterUsers = (FilterUsersDropDownList) FindControl("FilterUsers");
            threads = (Repeater) FindControl("Threads");
            announcements = (Repeater) FindControl("Announcements");
			subForumContainer = FindControl("SubForumContainer") as Control;
			subForums = FindControl("SubForumRepeater") as ForumRepeater;
            hideReadPosts = (HideReadPostsDropDownList) FindControl("HideReadPosts");
            threadSortddl = (ThreadSortDropDownList) FindControl("SortThreads");
            sortOrderddl = (SortOrderDropDownList) FindControl("SortOrder");
            forumFilterddl = (ForumDropDownList) FindControl("ForumDropDownList1");
            forumFilterText = (Label) FindControl("ForumFilterText");
            moveThreads = (LinkButton) FindControl("moveThreads");
            filterTopicRow = (HtmlTableRow) FindControl("FilterTopicRow");
            emailNotificationRow = (HtmlTableRow) FindControl("EmailNotificationRow");
            ddlTracking = (EmailNotificationDropDownList) FindControl("ForumTrackingDDL");                                    
            sortButton = (Button) FindControl("SortThreadsButton");
            rememberSettingsButton = (Button) FindControl("RememberSettingsButton");
            dateFilter = (DateFilter) FindControl("DateFilter");
            pager = (ForumPager) FindControl("Pager");
            pager2 = (ForumPager) FindControl("Pager2");
            currentPage = (CurrentPage) FindControl("CurrentPage");
            currentPage2 = (CurrentPage) FindControl("CurrentPage2");
            newPostButton = (ForumImageButton) FindControl("NewPostButton");
			poll = (ForumImageButton) FindControl("Poll");
			newPostButtonDown = (ForumImageButton) FindControl("NewPostButtonDown");
			forumSettings = (ForumImageButton) FindControl("ForumSettings");
            //postbackSourceControl = GetPostBackControl();
			aggregateRssLink = (AggregateRssLink) FindControl("aggregateRssLink");
			rssLink = (RssLink) FindControl("rssLink");

            InitializeChildControls();
        }

        private void InitializeChildControls() 
        {
            if (announcements != null)
                announcements.ItemDataBound += new RepeaterItemEventHandler( Threads_ItemDataBound );

            if (threads != null)
                threads.ItemDataBound += new RepeaterItemEventHandler( Threads_ItemDataBound );		

            // We don't need to move threads that are private messages, so the skin doesn't have the move button.
            //
            if (moveThreads != null && 
                mode != ThreadViewMode.PrivateMessages)
            {
                moveThreads.Click += new EventHandler( MoveThreads_OnClick );
            }

            if (sortButton != null) 
                sortButton.Click += new EventHandler( ThreadFilterSettings_Changed );

            if (rememberSettingsButton != null) 
                rememberSettingsButton.Click += new EventHandler( RememberThreadFilterSettings_Click );

            if (forumFilterddl != null)
            {
                switch (mode) 
                {
                    case ThreadViewMode.Active:
                    case ThreadViewMode.Unanswered:
                    case ThreadViewMode.NotRead:
					case ThreadViewMode.MyForums:
                        forumFilterddl.SelectedIndexChanged += new EventHandler( ForumFilter_Changed );
                        break;
                }
            }

			if (dateFilter != null)
			{
				if ((mode != ThreadViewMode.Default) && (mode != ThreadViewMode.PrivateMessages))
				{
					if ((FindControl("DateFilter2") as DateFilter) != null)
					{
						dateFilter = FindControl("DateFilter2") as DateFilter;
						dateFilter.Visible = true;
						dateFilter.DateChanged += new EventHandler( ForumFilter_Changed );
					}
				}
			}
        }
		        
        #endregion

        #region Properties

        /// <value>
        /// Controls the mode that the thread view control displays
        /// </value>
        public ThreadViewMode ThreadViewMode 
        {
            get { return mode; }
            set { mode = value; }
        }

        #endregion

        #region Event Handlers

        #region ForumFilter_Changed
        /// <summary>
        /// Fired when thread's forum filter has changed.
        /// </summary>
        public void ForumFilter_Changed (Object sender, EventArgs e) 
        {
            // Set pager to 1st page
            pager.PageIndex = 0;

			if (dateFilter != null)
				dateFilterMode = dateFilter.SelectedValue;

            DataBind();
        }
        #endregion

        #region ThreadFilterSettings_Changed
        /// <summary>
        /// Fired when current thread's filter settigs should be changed 
        /// and applied.
        /// </summary>
        public void ThreadFilterSettings_Changed(Object sender, EventArgs e) 
        {
            // Set pager to 1st page
            //
            pager.PageIndex = 0;

            // If user have chosen Apply then we shall use local filter.
            // This applies only to authenticated users.
            //
            authUseLocalFilter = true;

            // Update filtering field values
            //
            this.SetFilteringFieldValues();
            
            DataBind();
        }
        #endregion

        #region RememberThreadFilterSettings_Click
        /// <summary>
        /// Fired when current thread's filter settigs should be remembered 
        /// in current user's cookie and applied.
        /// </summary>
        public void RememberThreadFilterSettings_Click(Object sender, EventArgs e) 
        {
            // Save changed thread filter settings 
            //
            // Save in cookie
            string forumSettings = (int) threadSortddl.SelectedValue + ":" + (int) sortOrderddl.SelectedValue + ":" + (int) dateFilter.SelectedValue + ":" + hideReadPosts.SelectedValue.ToString().Substring(0,1) + ":" + (int) filterUsers.SelectedValue;
            UserCookie userCookie = new UserCookie( csContext.User );
            userCookie.SaveForumOptions( csContext.SectionID, forumSettings );
            
            // Use remembered user filter just in case
            //
            authUseLocalFilter = false;

            // Update filtering field values
            //
            this.SetFilteringFieldValues();
            
            // DB save of Email Notification value
            //
            if (ddlTracking != null && !ddlTracking.AutoPostBack)
            {
                ThreadTracking.SetSectionSubscriptionType( csContext.SectionID, (EmailSubscriptionType) Int32.Parse( ddlTracking.SelectedValue ) );
            }

            DataBind();
        }
        #endregion

        #region Threads_ItemDataBound
        /// <summary>
        /// Added to handle Username displaying
        /// </summary>
        protected void Threads_ItemDataBound (Object Sender, RepeaterItemEventArgs e) 
        {
            Thread thread = e.Item.DataItem as Thread;
            if (thread == null)
                return;
            
            bool isAnonymousPostingEnabled = thread.IsAnonymousPost && 
                ForumConfiguration.Instance().EnableUserPostingAsAnonymous &&
                thread.Forum.EnableAnonymousPostingForUsers;

            switch (e.Item.ItemType) 
            {
                case  ListItemType.Item:
                case  ListItemType.AlternatingItem:
                    IText userName = TextControlHelper.Create(e.Item.FindControl( "UsernameLink" ));
                    if (userName != null) 
                    {
                        userName.Text = Formatter.FormatUsername( thread.AuthorID, thread.Username, isAnonymousPostingEnabled, false, thread.ThreadShouldBeIgnored ); 
                    }

                    ThreadStatusImage statusImage = e.Item.FindControl( "ThreadItemStatusImage" ) as ThreadStatusImage;
                    if (statusImage != null && 
                        forum != null &&
                        !forum.EnableThreadStatus)
                    {
                        //statusImage.ThreadStatus = ThreadStatus.NotSet;
                        statusImage.Visible = false;
                    }
                    break;
            }
        }
        #endregion

        #region MoveThreads_OnClick
        protected void MoveThreads_OnClick(object sender, EventArgs e)
        {
            // Update filtering field values
            //
            this.SetFilteringFieldValues();
            
            string threadsToMove = String.Empty;
        
            foreach (RepeaterItem item in threads.Items)
            {
                MoveThreadCheckBox chkMove = (MoveThreadCheckBox)item.FindControl("moveThisThread");
                
                if (chkMove != null && 
                    chkMove.Checked)
                {
                    threadsToMove += chkMove.Value + ",";
                }
                                    
            }

            if (threadsToMove.Length > 0)
            {
                // If there are threads to move, chop off the trailing comma. 
                threadsToMove = threadsToMove.TrimEnd( ',' );

                // Redirect to the ThreadsMove page. 
                HttpContext.Current.Response.Redirect(Globals.GetSiteUrls().ModerateThreadsMove(threadsToMove, HttpContext.Current.Request.Url.ToString()), true);
                
            }
        }
        #endregion

        #endregion

        #region Internal Helpers

        #region SetFilteringControlValues
        /// <summary>
        /// Update filtering controls' values.
        /// </summary>
        private void SetFilteringControlValues ()
        {
            // Set filters
            //
            this.LoadThreadListFilter();

            // Adjust visibility for some of them if
            // we have an anonymous user.
            //
            if (csContext.User.IsAnonymous) 
            {
                if (filterUsers != null)
                    filterUsers.Visible = false;

                if (hideReadPosts != null)
                    hideReadPosts.Visible = false;

                if (rememberSettingsButton != null)
                    rememberSettingsButton.Visible = false;

                if (filterTopicRow != null)
                    filterTopicRow.Visible = false;
                
                if (emailNotificationRow != null)
                    emailNotificationRow.Visible = false;
            }

            // Set the following values anyway
            //
            if (dateFilter != null)
                dateFilter.SelectedValue = dateFilterMode; //.Items.FindByValue( ((int) dateFilterMode).ToString() ).Selected = true;

            if (threadSortddl != null)
                threadSortddl.SelectedValue = sortBy;

            if (threadSortddl != null)
                sortOrderddl.SelectedValue = sortOrder;
        
            // Set values if authenticated only
            //
            if (!csContext.User.IsAnonymous)
            {
                if (hideReadPosts != null)
                    hideReadPosts.SelectedValue = hideReadPost;

                if (filterUsers != null)
                    filterUsers.SelectedValue = userFilter;
            }
        }
        #endregion
        
        #region SetFilteringFieldValues
        /// <summary>
        /// Update filtering field's values.
        /// </summary>
        private void SetFilteringFieldValues ()
        {
            if (dateFilter != null)
                dateFilterMode = dateFilter.SelectedValue;

            if (threadSortddl != null)
                sortBy = threadSortddl.SelectedValue;

            if (threadSortddl != null)
                sortOrder = sortOrderddl.SelectedValue;
        
            // Those are for authenticated users only
            //
            if (!csContext.User.IsAnonymous) 
            {
                if (hideReadPosts != null)
                    hideReadPost = hideReadPosts.SelectedValue;

                if (filterUsers != null)
                    userFilter = filterUsers.SelectedValue;
            }
        }
        #endregion

        #region LoadThreadListFilter
        /// <summary>
        /// Init filtering values based on user's credentials.
        /// </summary>
        private void LoadThreadListFilter ()
        {
            // Load query string values. 
            // We do not care if user is authenticated or not.
            // This will make the code simpler.
            //
            LoadQuerystringFilter();

            // We have to check if we want to use local set filter or 
            // the previous remembered one.
            //
            if (!csContext.User.IsAnonymous && 
                !authUseLocalFilter)
            {
                // If we have an authenticated user try to
                // get filer constraint form its cookie.
                // Otherwise load it form the query string as well.
                //
                UserCookie cookie = new UserCookie( csContext.User );
                ForumUserOptions options = cookie.GetForumOptions( csContext.SectionID );
                if (options.HasSettings) 
                {    
                    dateFilterMode = options.DateFilter;
                    sortBy = options.SortBy;
                    sortOrder = options.SortOrder;
                    userFilter = options.UserFilter;
                    hideReadPost = options.HideReadPosts;
                }
            }            
        }
        #endregion

        #region LoadQuerystringFilter
        /// <summary>
        /// Load filtering values form query string.
        /// Also validate it.
        /// </summary>
        private void LoadQuerystringFilter ()
        {
            // Date filter
            int _dateFilter = csContext.GetIntFromQueryString( "df", -1 );
            if ((_dateFilter > -1) &&
                (_dateFilter >= (int) ThreadDateFilterMode.LastVisit) &&
                (_dateFilter <= (int) ThreadDateFilterMode.All))
            {
                dateFilterMode = (ThreadDateFilterMode) _dateFilter;                    
            }
            else
            {
                // Get default config value
                dateFilterMode = csContext.SiteSettings.DefaultThreadDateFilter;                    
            }

            // Sort by
            int _sortBy = csContext.GetIntFromQueryString( "sb", -1 );
            if ((_sortBy > -1) && 
                (_sortBy >= (int) SortThreadsBy.LastPost) &&
                (_sortBy <= (int) SortThreadsBy.Subject))
            {
                sortBy = (SortThreadsBy) _sortBy;                    
            }
            else
            {
                sortBy = SortThreadsBy.LastPost;                    
            }

            // Sort order
            int _sortOrder = csContext.GetIntFromQueryString( "d", -1 );
            if ((_sortOrder > -1) &&
                (_sortOrder == (int) SortOrder.Ascending || 
                _sortOrder == (int) SortOrder.Descending))
            {
                sortOrder = (SortOrder) _sortOrder;
            }
            else
            {
                sortOrder = SortOrder.Descending;
            }
            
            /*
            if (csContext.User.IsAnonymous)
                return;
            */

            // User filter
            int _userFilter = csContext.GetIntFromQueryString( "uf", -1 );
            if ((_userFilter > -1) &&
                (_userFilter >= (int) ThreadUsersFilter.All) &&
                (_userFilter <= (int) ThreadUsersFilter.HideTopicsByNonAnonymousUsers))
            {
                userFilter = (ThreadUsersFilter) _userFilter;
            }
            else
            {
                userFilter = ThreadUsersFilter.All;
            }

            // Hide read posts
            int _hideReadPost = csContext.GetIntFromQueryString( "hrp", -1 );
            if ((_hideReadPost > -1) &&
                (_hideReadPost == 0 || 
                _hideReadPost == 1))
            {
                hideReadPost = Convert.ToBoolean( _hideReadPost );
            }
            else
            {
                hideReadPost = false;
            }
            
            // Use local filter in exchange of user set filter
            int _authUseLocalSettings = csContext.GetIntFromQueryString( "lf", -1 );
            if ((_authUseLocalSettings > -1) &&
                (_authUseLocalSettings == 0 || 
                _authUseLocalSettings == 1))
            {
                authUseLocalFilter = Convert.ToBoolean( _authUseLocalSettings );
            }
            else
            {
                authUseLocalFilter = false;
            }           
        }
        #endregion

        #region BuildQuerystringFilter
        /// <summary>
        /// Add filtering values as query string params to the provided base url.
        /// </summary>
        private string BuildQuerystringFilter (string baseUrl, ThreadViewMode mode)
        {
            string qsFilter = "";
            string linkQsChar = "?"; // default

            // Try to figure out if url is rewrited 
            // to set the link char between provided base url
            // and our new query string params.
            //
            if (baseUrl.IndexOf( "?", 0 ) > 1)
            {
                linkQsChar = "&";
            }

            // Is an anonymous user?
            //
            if (csContext.User.IsAnonymous) 
            {
                qsFilter = string.Format( anonymousQuerystringFilter,
                    "{0}",
                    (int) sortBy, 
                    (int) sortOrder, 
                    (int) dateFilterMode 
                    );
            }
            else
            {
                // Which thread view mode?
                //
                switch (mode)
                {
                    case ThreadViewMode.PrivateMessages:
                        qsFilter = string.Format( anonymousQuerystringFilter,
                            "{0}",
                            (int) sortBy, 
                            (int) sortOrder, 
                            (int) dateFilterMode 
                            );
                        break;
                        //case ThreadViewMode.MyForums:
                    default:
                        qsFilter = string.Format( authQuerystringFilter,
                            "{0}",
                            (int) sortBy, 
                            (int) sortOrder, 
                            (int) dateFilterMode,
                            (int) userFilter,
                            ((hideReadPost == true) ? 1 : 0),
                            ((authUseLocalFilter == true) ? 1 : 0)
                            );
                        break;
                }
            }

            return RemoveDuplicateQueryStringParameters(baseUrl + linkQsChar + qsFilter);
        }

		private string RemoveDuplicateQueryStringParameters(string url)
		{
			string path = url.Substring(0, url.IndexOf("?") + 1);
			string queryString = url.Substring(url.IndexOf("?") + 1);
			System.Collections.ArrayList paramNames = new System.Collections.ArrayList();
			System.Collections.ArrayList paramPairs = new System.Collections.ArrayList();

			string[] pairs = queryString.Split('&');
			foreach (string pair in pairs)
			{
				string[] items = pair.Split('=');

				if (!paramNames.Contains(items[0]))
				{
					paramNames.Add(items[0]);
					paramPairs.Add(pair);
				}
			}

			return path + string.Join("&", (string[])paramPairs.ToArray(typeof(string)));
		}
        #endregion

        #endregion
    }
}
